﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProdeManagmente.Model;
using ProdeManagmente.Libs;
using System.Data;

namespace ProdeManagmente.DAO
{
    public class ResultService
    {
        private static ResultService instance;
        private static String TBResult = "Result";

        private ResultService()
        { }

        public static ResultService getResultServiceInstance()
        {
            if (instance == null)
            {
                instance = new ResultService();
            }
            return instance;
        }

        public Result getResultByIdMatch(long idMatch)
        {
            Result result = null;

            Persistencia conn = Persistencia.getInstance();

            String SQL = "SELECT * FROM " + TBResult + " " +
                            "WHERE idMatch = " + idMatch;

            DataTable resultTable = conn.executeQuery(SQL);

            foreach (DataRow resultRow in resultTable.Rows)
            {
                result = getResult(resultRow);
            }

            return result;
        }

        /**
         * Obtiene la lista de Resultados,  filtro SIN la palabra clave WHERE
         */
        public List<Result> getResultListFilter(String filter)
        {
            List<Result> resultList = new List<Result>();

            Persistencia conn = Persistencia.getInstance();
            String SQL = "SELECT * FROM " + TBResult + " ";

            if (!filter.Trim().Equals(""))
            {
                SQL = SQL + "WHERE " + filter;
            }

            DataTable resultTable = conn.executeQuery(SQL);

            foreach (DataRow resultRow in resultTable.Rows)
            {
                Result result = getResult(resultRow);
                resultList.Add(result);
            }
            return resultList;
        }

        public Result save(Result result)
        {
            Persistencia conn = Persistencia.getInstance();
            String SQL = "";

            if (getResultByIdMatch(result.getMatch().getId()) != null) //Si es diferente de null es por que ya existe entonces tiene que actualizarlo
            {
                SQL = "UPDATE  " + TBResult + " SET " +
                      "VTeam1 = " + result.getVTeam1() + ", " +
                      "VTeam2 = " + result.getVTeam2() + ", " +
                      "PTeam1 = " + result.getPTeam1() + ", " +
                      "PTeam2 = " + result.getPTeam2() + ", " +
                      "FinalResult = " + Convert.ToInt32(result.getFinalResult()) + " " +
                      "WHERE idMatch = " + result.getMatch().getId() + " ";
            }
            else //Si es null es por que es un objeto nuevo
            {
                SQL = "INSERT INTO " + TBResult + " " +
                       "(idMatch, VTeam1, VTeam2, PTeam1, PTeam2, FinalResult) VALUES (" +
                       "" + result.getMatch().getId() + ", " +
                       "" + result.getVTeam1() + ", " +
                       "" + result.getVTeam2() + ", " +
                       "" + result.getPTeam1() + ", " +
                       "" + result.getPTeam2() + ", " +
                       "" + Convert.ToInt32(result.getFinalResult()) + ") ";
            }

            int resultNumber = Convert.ToInt32(conn.ExecuteNonQuery(SQL));

            if (result.getFinalResult())
            {
                saveUserPoints(result);
            }

            if (resultNumber <= 0)
            {
                throw new BusinessException("302", "No se pudo grabar el elemento");
            }

            return result;
        }

        private void saveUserPoints(Result result)
        {
            UserResultService userResultService = UserResultService.getUserResultServiceInstance();

            String SQL = "idMatch = " + result.getMatch().getId() + " ";
            List<UserResult> userResultList = userResultService.getUserResultListFilter(SQL);

            foreach (UserResult userResult in userResultList)
            {
                int point = compareUserResult(result, userResult);
                userResult.addPoints(point);

                userResultService.save(userResult);
            }

        }

        private int compareUserResult(Result result, UserResult UserResult)
        { 
            int points = 0;
            int won = 0;
            int userWon = 0;

            won = whoWon(result);
            userWon = whoWonUser(UserResult);

            if (won == userWon)
            {
                points = 1;
            }           

            if (result.getVTeam1() == UserResult.getVTeam1() && result.getVTeam2() == UserResult.getVTeam2())
            {
                points = 3;
            }

            return points;
        }

        private int whoWon(Result result)
        {
            int won = 0;
            //Si el valor 1 es mayor a valor 2 entonces gano el equipo uno
            if (result.getVTeam1() > result.getVTeam2())
            {
                won = 1;
            }
            else if (result.getVTeam1() < result.getVTeam2())
            {
                won = 2;
            }
            else //Si son iguales mira penales
            {
                if (result.getPTeam1() > result.getPTeam2())
                {
                    won = 1;
                }
                else if (result.getPTeam1() < result.getPTeam2())
                {
                    won = 2;
                }
            }
            return won;
        }

        private int whoWonUser(UserResult result)
        {
            int won = 0;
            //Si el valor 1 es mayor a valor 2 entonces gano el equipo uno
            if (result.getVTeam1() > result.getVTeam2())
            {
                won = 1;
            }
            else if (result.getVTeam1() < result.getVTeam2())
            {
                won = 2;
            }
            else //Si son iguales mira penales
            {
                won = 0;
            }
            return won;
        }


        public void delete(long idMatch)
        {
            Persistencia conn = Persistencia.getInstance();
            String SQL = "";

            SQL = "DELETE  " + TBResult + "  " +
                    "WHERE idMatch = " + idMatch + " ";

            int result = Convert.ToInt32(conn.ExecuteNonQuery(SQL));
            if (result <= 0)
            {
                throw new BusinessException("303", "No se pudo borrar el elemento");
            }
        }

        private Result getResult(DataRow resultRow)
        {
            Result result = null;

            MatchService matchService = MatchService.getMatchServiceInstance();
            Match match = matchService.getMatchById(Convert.ToInt64(resultRow["idMatch"].ToString()));
            int PTeam1 = 0;
            int PTeam2 = 0;

            if (!resultRow["PTeam1"].ToString().Equals(""))
            {
                PTeam1 = Convert.ToInt32(resultRow["PTeam1"].ToString());
            }

            if (!resultRow["PTeam2"].ToString().Equals(""))
            {
                PTeam2 = Convert.ToInt32(resultRow["PTeam2"].ToString());
            }

            result = new Result(match,
                            Convert.ToInt32(resultRow["VTeam1"].ToString()),
                            Convert.ToInt32(resultRow["VTeam2"].ToString()),
                            PTeam1,
                            PTeam2,
                            resultRow["FinalResult"].ToString() == "1");

            return result;
        }
    }
}
